#pragma once
#ifndef ANIMATION_H_
#define ANIMATION_H_

#include "image.h"

namespace EPOC
{
	const unsigned int DEFAULT_FRAMERATE = 16;

	/**
	* Animation class
	* This class add the functionality to use an image with many frames as an animation
	*/
	class Animation : public Image
	{
	public:
		/**
		* Enumeration of animation types
		* @see GetAnimationType()
		* @see SetAnimationType()
		*/
		enum ANIMATION_TYPE
		{
			kANIMATION_TYPE_UNKNOWN,
			kANIMATION_TYPE_NORMAL,
			kANIMATION_TYPE_REVERSE,
			kANIMATION_TYPE_LOOP,
			kANIMATION_TYPE_PINGPONG,
			kANIMATION_TYPE_MANUAL
		};

		/**
		* Enumeration of animation frame modes
		* @see GetFrameMode()
		* @see SetFrameMode()
		*/
		enum ANIMATION_FRAMEMODE
		{
			kANIMATION_FRAMEMODE_UNKNOWN,
			kANIMATION_FRAMEMODE_NORMAL,
			kANIMATION_FRAMEMODE_LIMITS
		};

	public:
			
		/**
		* Contructor
		* Resets all members to the default values
		*/
		Animation();
		
		/**
		* Destructor
		* */
		virtual ~Animation();

		/**
		* Updates the animation
		* @remark This function is called once per frame internally by EpGraphicsManager if the animation is create from it.
		* @param fTimeDelta the time that has passed since last update, measured in milliseconds
		* @return true if the update succeeded and false if it didn't
		*/
		virtual bool Update(float fTimeDelta);
		
		/**
		* Resets the animation and it's data
		*/
		virtual void Reset();

		/**
		* Sets the number of times to loop the animation
		* @param nLoops The number of times to loop the animation. 0 = Play animation once, 1 or greater = Loop animation N times
		* @see GetLoops()
		*/
		inline void SetLoops(unsigned int nLoops) { m_nLoops = nLoops;}

		/**
		* Returns the number of times to loop the animation
		* @return The number of times to loop the animation
		* @see SetLoops()
		*/
		inline unsigned int GetLoops() { return m_nLoops;}

		/**
		* Sets the framerate of the animation. The frame rate is described in frames per second
		* @param fFrameRate The number of frames per second of the animation
		* @see GetFrameRate()
		*/
		inline void SetFrameRate(float fFrameRate)			{ m_fFrameRate = fFrameRate;}
		
		/**
		* Returns the framerate of the animation. The frame rate is described in frames per second
		* @param fFrameRate The number of frames per second of the animation
		* @see GetFrameRate()
		*/
		inline float GetFrameRate()							{ return m_fFrameRate;}

		/**
		* Sets the type of the animation
		* @param m_nAnimationType The animation type to be used by the animation
		* @see GetAnimationType()
		* @see ANIMATION_TYPE
		*/
		inline void SetAnimationType(ANIMATION_TYPE nAnimationType){ m_nAnimationType = nAnimationType;}

		/**
		* Returns the type of the animation
		* @return The animation type used by the animation
		* @see GetAnimationType()
		* @see ANIMATION_TYPE
		*/
		inline ANIMATION_TYPE GetAnimationType() { return m_nAnimationType;}
		
		
		/**
		* Sets the frame mode used by the animation
		* @remark Frame modes is used when an animation contains several animations to limit between wich frames the animation is animated.
		* @param nFrameMode The frame mode to be used by the animation
		* @see GetAnimationType()
		* @see ANIMATION_FRAMEMODE
		*/
		inline void SetFrameMode(ANIMATION_FRAMEMODE nFrameMode) { m_nFrameMode = nFrameMode;}
		
		/**
		* Returns the frame mode to be used by the animation
		* @param nMode The frame mode to be used by the animation
		* @see SetFrameMode()
		* @see ANIMATION_FRAMEMODE
		*/
		inline ANIMATION_FRAMEMODE GetFrameMode() { return m_nFrameMode;}

		/**
		* Sets a flag that tells the animation to return false from the update method when the animation has reched the end. When this happens EPOC will delete the animation.
		* @remark This flag should be used carefully. You should only use it for the fire-and-forget type of animations i.e. effects like explosions and so forth.
		* @param bRemoveStatus True or false
		* @see IsRemoveWhenDoneEnabled()
		*/
		inline void SetRemoveWhenDone(bool bRemoveStatus)	{ m_bRemoveDone = bRemoveStatus;}
		
		/**
		* Returns wether the animation is flagged to be removed at the end of the animation or not
		* @return True or false
		* @see SetRemoveWhenDone()
		*/
		inline bool IsRemoveWhenDoneEnabled() { return m_bRemoveDone;}

		/**
		* Returns wether the animation has reached the end of the animation
		* @return True or false
		*/
		inline bool IsDone() { return m_bDone;}

		/**
		* Sets the start frame of the frame limit
		* @see SetFrameMode()
		* @see GetFrameMode()
		* @see EP_ANIMATION_FRAMEMODE
		*/
		inline void SetFrameLimitStart(int nFrame) { m_nFrameLimitStart = nFrame;}

		/**
		* Returns the start frame of the frame limit
		* @see SetFrameMode()
		* @see GetFrameMode()
		* @see EP_ANIMATION_FRAMEMODE
		* @return The start frame of the frame limits
		*/
		inline int GetFrameLimitStart() { return m_nFrameLimitStart;}
		
		/**
		* Sets the end frame of the frame limit
		* @see SetFrameMode()
		* @see GetFrameMode()
		* @see EP_ANIMATION_FRAMEMODE
		*/
		inline void SetFrameLimitEnd(unsigned int nFrame) { m_nFrameLimitEnd = nFrame;}
		
		/**
		* Returns the end frame of the frame limit
		* @see SetFrameMode()
		* @see GetFrameMode()
		* @see EP_ANIMATION_FRAMEMODE
		* @return The end frame of the frame limits
		*/
		inline unsigned int GetFrameLimitEnd() { return m_nFrameLimitEnd;}


	protected:
		
		/**
		* Updates the current frame counter. This is done different based on the animation type
		*/
		void StepFrame();

		/**
		* Updates and limits the frame counter and checks wether the animation has finished (inluding loops)
		* @return True if animation is finished, false if it hasn't
		*/
		bool CheckFrame();

	protected:
		bool m_bRemoveDone;					///< Flag telling wether the animation should return from false when the end is reached or not.
		bool m_bDone;						///< Flag telling wether the animations has reached the end or not.
		bool m_bReverse;					///< Flag telling if the animation is animating in reverse or not.
		unsigned int m_nLoops;				///< The number of times to loop the animation
		unsigned int m_nFrameLimitStart;	///< The start frame of the frame limit
		unsigned int m_nFrameLimitEnd;		///< The end frame of the frame limit
		float m_fFrameTimer;				///< Counter used to calculate when to present the next frame
		float m_fFrameRate;					///< The frame rate of the animation

		ANIMATION_TYPE m_nAnimationType;	///< The animation type used by the animation
		ANIMATION_FRAMEMODE m_nFrameMode;	///< The frame mode used by the animation
	
	}; // class Animation
}; // namespace EPOC

#endif